package com.feinno.urcs.group.http.servlet;

import com.feinno.threading.Future;
import com.feinno.urcs.auth.AuthorizationResult;
import com.feinno.urcs.auth.token.HttpTokenAuthorizationService;
import com.feinno.urcs.group.GroupConfiguration;
import com.feinno.urcs.group.http.auth.HttpDigest;
import com.feinno.urcs.group.http.util.HttpHelper;
import com.feinno.urcs.group.http.util.StringHelper;
import com.feinno.urcs.group.http.util.XcapParser;
import com.feinno.urcs.nai.IMPU;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sip.address.SipURI;
import javax.sip.address.URI;
import java.io.IOException;

/**
 * Created by wuzhiguo on 15-5-11.
 */
public abstract class BaseHttpServlet extends HttpServlet {

	private static final Logger LOGGER = LoggerFactory.getLogger(BaseHttpServlet.class);

	protected IMPU parseSenderIMPU(final HttpServletRequest request) {
		try {
			String sender = request.getHeader("X-3GPP-Intended-Identity");
			if (!StringHelper.isNullOrEmpty(sender)) {
				return IMPU.parse(sender);
			}
		} catch (Exception ex) {
			String requestString = HttpHelper.getRequestString(request);
			LOGGER.error(String.format("parseSenderIMPU() Error. Received Request: %s", requestString));
		}

		return null;
	}

	protected IMPU parseXuiIMPU(final HttpServletRequest request, final XcapParser parser) {
		try {
			String xui = parser.getXui();
			if (!StringHelper.isNullOrEmpty(xui)) {
				return IMPU.parse(xui);
			}
		} catch (Exception ex) {
			String requestString = HttpHelper.getRequestString(request);
			LOGGER.error(String.format("parseXuiIMPU() Error. Received Request: %s", requestString));
		}

		return null;
	}

	protected IMPU parseTargetIMPU(final HttpServletRequest request, final XcapParser parser) {
		try {
			if (parser.getNodeSelectorArray() != null && parser.getNodeSelectorArray().length > 3) {
				String entryString = parser.getNodeSelectorArray()[3];
				final String beginString = "entry[@uri=";
				final String endString = "]";
				if (entryString.startsWith(beginString) && entryString.endsWith(endString)) {
					String target = entryString.substring(beginString.length(), entryString.length() - endString.length());
					target = StringHelper.trimQuoteChar(target);
					if (!StringHelper.isNullOrEmpty(target)) {
						return IMPU.parse(target);
					}
				}
			}
		} catch (Exception ex) {
			String requestString = HttpHelper.getRequestString(request);
			LOGGER.error(String.format("parseTargetIMPU() Error. Received Request: %s", requestString));
		}

		return null;
	}

	protected void checkAuthorization(final GroupHttpContext ctx, HttpTokenAuthorizationService httpTokenAuthorizationService, final AuthHandler authHandler) throws IOException {
		try {
			if (LOGGER.isInfoEnabled()) {
				String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
				LOGGER.info(String.format("Received Request: %s", requestString));
			}

			String authorization = ctx.getRequest().getHeader("Authorization");
			if (!StringHelper.isNullOrEmpty(authorization)) {
				if (authorization.trim().startsWith("Digest")) {
					checkDigestAuthorization(ctx, authHandler);
					return;
				} else if (authorization.trim().startsWith("UA")) {
					checkUAAuthorization(ctx, httpTokenAuthorizationService, authHandler);
					return;
				}
			}

			checkDigestAuthorization(ctx, authHandler);

		} catch (Exception ex) {
			String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
			LOGGER.error(String.format("checkAuthorization() Error. Received Request: %s", requestString), ex);
			authHandler.run(500, "ServerError");
		}
	}

	protected void checkDigestAuthorization(final GroupHttpContext ctx, final AuthHandler authHandler) throws IOException {
		ctx.getRequest().setAttribute("Authorization", "Digest");
		authHandler.run(200, "OK");
	}

	protected void checkUAAuthorization(final GroupHttpContext ctx, HttpTokenAuthorizationService httpTokenAuthorizationService, final AuthHandler authHandler) throws Exception {

		HttpServletRequest request = ctx.getRequest();
		HttpServletResponse response = ctx.getResponse();
		Future<AuthorizationResult> future = httpTokenAuthorizationService.checkAuthorization(request, response);
		AuthorizationResult authorizationResult = future.getValue();
		int statusCode = 200;
		String description = "OK";
		if (authorizationResult != null) {
			switch (authorizationResult) {
				case OK:
					statusCode = 200;
					description = "OK";
					break;
				case BADREQUEST:
					statusCode = 400;
					description = "Bad Request";
					break;
				case FORBIDDEN:
					statusCode = 403;
					description = "Forbidden";
					break;
				case ERROR:
				default:
					statusCode = 500;
					description = "Server Error";
					break;

			}
		}
		authHandler.run(statusCode, description);
	}

	protected void setDigestAuthenticationInfo(final GroupHttpContext ctx) {
		if (ctx.getRequest().getAttribute("Authorization") != null && ctx.getRequest().getAttribute("Authorization").toString().equals("Digest")) {
			String authenticationInfo = HttpDigest.buildAuthenticationInfoHeaderValue(HttpDigest.generateRandomString());
			ctx.getResponse().setHeader(HttpDigest.HEADER_AUTHENTICATION_INFO, authenticationInfo);
		}
	}

	public void process(final GroupHttpContext ctx) throws IOException {
		throw new IOException("BaseHttpServlet process()...");
	}


//	protected String getMobileNo(URI uri) {
//		if (uri == null) {
//			return null;
//		} else if (uri.isSipURI()) {
//			return ((SipUri) uri).getUser();
//		} else {
//			return "+" + ((TelURI) uri).getPhoneNumber();
//		}
//	}

	protected int getGroupIdFromUri(String groupUri) {
		URI uri = IMPU.parse(groupUri).toUri();
		if (uri.isSipURI()) {
			String gId = ((SipURI) uri).getUser().toString();
			return Integer.parseInt(gId.substring(GroupConfiguration.INSTANCE.getGroupPrefix().length()));
		} else {
			return 0;
		}
	}
}
